package page;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.apache.http.HttpStatus;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import util.FileTool;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.List;

public class RequestAndResponseTool {

    public static Page sendRequstAndGetResponseByGet(String url) throws Exception{
        Page page = null;
        // 1.生成 HttpClinet 对象并设置参数
        HttpClientBuilder builder = HttpClients.custom();
//对照UA字串的标准格式理解一下每部分的意思
        builder.setUserAgent("Mozilla/5.0(Windows;U;Windows NT 5.1;en-US;rv:0.9.4)");
        final CloseableHttpClient httpClient = builder.build();

        RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD)
                .setConnectionRequestTimeout(20000).setConnectTimeout(20000)
                .setSocketTimeout(20000).build();//设置请求的状态参数
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(requestConfig);

        CloseableHttpResponse response = null;
        // 3.执行 HTTP GET 请求
        response = httpClient.execute(httpGet);//返回请求执行结果
        int statusCode = response.getStatusLine().getStatusCode();
        // 判断访问的状态码
        if (statusCode != HttpStatus.SC_OK) {
            System.err.println("Method failed: " + statusCode);
        }

        // 4.处理 HTTP 响应内容
        String html = EntityUtils.toString(response.getEntity(), "UTF-8");// 读取为字节 数组
        String contentType = response.getHeaders("Content-Type")[0].getValue(); // 得到当前返回类型
        page = new Page(html,url,contentType); //封装成为页面

        response.close();

        return page;
    }

    public static Page sendRequstAndGetResponse(String url) {
        Page page = null;
        // 1.生成 HttpClinet 对象并设置参数
        HttpClientBuilder builder = HttpClients.custom();
//对照UA字串的标准格式理解一下每部分的意思
        builder.setUserAgent("Mozilla/5.0(Windows;U;Windows NT 5.1;en-US;rv:0.9.4)");
        final CloseableHttpClient httpClient = builder.build();

        RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD)
                .setConnectionRequestTimeout(3000).setConnectTimeout(3000)
                .setSocketTimeout(3000).build();//设置请求的状态参数
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(requestConfig);

        CloseableHttpResponse response = null;
        // 3.执行 HTTP GET 请求
        try {
            response = httpClient.execute(httpGet);//返回请求执行结果
            int statusCode = response.getStatusLine().getStatusCode();
            // 判断访问的状态码
            if (statusCode != HttpStatus.SC_OK) {
                System.err.println("Method failed: " + statusCode);
            }

            // 4.处理 HTTP 响应内容
            String html = EntityUtils.toString(response.getEntity(), "UTF-8");// 读取为字节 数组
            String contentType = response.getHeaders("Content-Type")[0].getValue(); // 得到当前返回类型
            page = new Page(html,url,contentType); //封装成为页面
        } catch (Exception e) {
            // 发生网络异常
            e.printStackTrace();
        } finally {
            // 释放连接
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return page;
    }

    public static Page sendRequstAndGetResponse(List<BasicHeader> headerList,String url,CookieStore cookieStore) {
        Page page = null;

        HttpClientBuilder builder = HttpClients.custom();
        builder.setUserAgent("Mozilla/5.0(Windows;U;Windows NT 5.1;en-US;rv:0.9.4)");
        CloseableHttpClient httpClient = builder.build();
        if(cookieStore != null) {
            builder.setDefaultCookieStore(cookieStore);
            httpClient = builder.build();
        }

        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(120000).setSocketTimeout(60000).setConnectionRequestTimeout(60000).setCookieSpec(CookieSpecs.STANDARD).build();
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(requestConfig);
        HttpClientContext httpClientContext = HttpClientContext.create();

        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpGet,httpClientContext);
        } catch (IOException e) {
            e.printStackTrace();
        }
        cookieStore = httpClientContext.getCookieStore();
        byte[] responseBody = null;
        try {
//            System.out.println("Status" + httpClientContext.getResponse().getStatusLine().getStatusCode());
            responseBody = FileTool.getStrbeamAsByte(httpClientContext.getResponse().getEntity().getContent());// 读取为字节 数组
        } catch (IOException e) {
            e.printStackTrace();
        }
        page = new Page(responseBody,url,cookieStore);
        return page;
    }

    public static HtmlPage getHtmlPage(String url, int waitTime) {
        //设置浏览器版本
        WebClient webClient = new WebClient(BrowserVersion.CHROME);
        //是否使用不安全的SSL
        webClient.getOptions().setUseInsecureSSL(true);
        //启用JS解释器，默认为true
        webClient.getOptions().setJavaScriptEnabled(false);
        //禁用CSS
        webClient.getOptions().setCssEnabled(false);
        //js运行错误时，是否抛出异常
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        //状态码错误时，是否抛出异常
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
        //是否允许使用ActiveX
        webClient.getOptions().setActiveXNative(false);
        //等待js时间
        webClient.waitForBackgroundJavaScript(600*1000);
        //设置Ajax异步处理控制器即启用Ajax支持
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());
        //设置超时时间
        webClient.getOptions().setTimeout(waitTime);
        //不跟踪抓取
        webClient.getOptions().setDoNotTrackEnabled(false);
        try {
            //模拟浏览器打开一个目标网址
            HtmlPage htmlPage = webClient.getPage(url);
            //为了获取js执行的数据 线程开始沉睡等待
            Thread.sleep(1000);//这个线程的等待 因为js加载需要时间的
            return htmlPage;
        } catch (FailingHttpStatusCodeException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
